package com.google.code.gaeapptest.servlet;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.logging.Logger;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.backends.BackendService;
import com.google.appengine.api.backends.BackendServiceFactory;
import com.google.code.gaeapptest.dao.Dao;
import com.google.code.gaeapptest.dao.DaoFactory;
import com.google.code.gaeapptest.domain.Test;
import com.google.code.gaeapptest.domain.TestCategory;
import com.google.code.gaeapptest.domain.TestData;
import com.google.code.gaeapptest.junit.BaseTest;
import com.google.code.gaeapptest.junit.GaeTest;

@SuppressWarnings("serial")
public class PlotDataServlet extends HttpServlet {
	private static final Logger LOG = Logger.getLogger(PlotDataServlet.class
			.getName());
	private static long msGmtToEst = 1000 * 60 * 60 * 5;

	public void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws IOException {

		// PARSE QUERY PARAMS
		final String callback = req.getParameter("callback");
		final String category = req.getParameter("category");
		final String testName = req.getParameter("testName");
		final String testList = req.getParameter("testList");
		final String testData = req.getParameter("testData");
		final String runTest = req.getParameter("runTest");

		Dao dao = DaoFactory.getInstance();
		BackendService backendsApi = BackendServiceFactory.getBackendService();
		String backend = backendsApi.getCurrentBackend();
		if (backend != null) {
			int instance = backendsApi.getCurrentInstance();
			LOG.info("background instance: " + instance);
			dao.updateMovingAverage("Transaction", "all");
			dao.updateMovingAverage("Entity", "all");
		} else if (runTest != null) {
			runTest(resp, category, testName);
		} else if (testList != null) {
			testList(resp, dao);
		} else if (testData != null) {
			testData(resp, dao, category, testName, callback);
		} else {
			resp.setContentType("text/html");
			resp.getWriter().println("Expected query params");
			LOG.info("Expected query params. url:"+ req.getRequestURI());
		}
	}

	// Run Junit Tests
	// http://localhost:8888/PlotData?runTest&category=File&testName=createFile&
	private void runTest(HttpServletResponse resp, String category,
			String testName) throws IOException {
		resp.setContentType("text/html");
		if (category != null) {
			if (testName != null) {
				LOG.fine("running category:[" + category + "] testName:["
						+ testName + "]");
				GaeTest t = BaseTest.getInstance(category);
				if (t != null) {
					@SuppressWarnings("rawtypes")
					Class partypes[] = new Class[0];
					Object arglist[] = new Object[0];
					try {
						Method meth = t.getClass()
								.getMethod(testName, partypes);
						meth.invoke(t, arglist);
						String msg = "runTests category:[" + category
								+ "] testName:[" + testName + "]  SUCCESS";
						LOG.fine(msg);
						resp.getWriter().println(msg);
					} catch (Exception e) {
						String msg = "runTests category:[" + category
								+ "] testName:[" + testName + "]  FAILURE:"
								+ e.getMessage();
						LOG.warning(msg);
						e.printStackTrace();
						resp.getWriter().println(msg);
					}
				} else {
					String msg = "FAILURE:  category:[" + category
							+ "] not found";
					LOG.warning(msg);
					resp.getWriter().println(msg);
				}
			} else {
				String msg = "FAILURE: Expected query param testName";
				LOG.warning(msg);
				resp.getWriter().println(msg);
			}
		} else {
			String msg = "FAILURE: Expected query param category";
			LOG.warning(msg);
			resp.getWriter().println(msg);
		}
	}

	// RETURN HTML LIST OF TESTS THAT CAN BE PLOTED
	// Eg http://localhost:8888/PlotData?testList
	private void testList(HttpServletResponse resp, Dao dao) throws IOException {
		resp.setContentType("text/html");
		List<TestCategory> categories = dao.getTestCategories();
		if (categories != null) {
			int i = 0;
			for (TestCategory tc : categories) {
				List<Test> tests = tc.tests;
				resp.getWriter().println(
						"<optgroup label=\"" + tc.category + "\" \">");
				for (Test t : tests) {
					resp.getWriter()
							.println(
									"<option "
											+ (i == 0 ? "selected=\"selected\""
													: "")
											+ " value=\"/PlotData?testData=true&category="
											+ tc.category + "&testName="
											+ t.name + "&callback=?\">"
											+ t.name + "</option>");

				}
				i++;
				resp.getWriter().println("</optgroup>");
			}
			LOG.fine("testLists:" + i);
		}

	}

	// RETURN THE TEST DATA
	// http://localhost:8888/PlotData?category=Transaction&testName=transactionTest1&callback=jQuery171025856821658089757_1328999087940&_=1328999088073
	private void testData(HttpServletResponse resp, Dao dao, String category,
			String testName, String callback) throws IOException {
		resp.setContentType("text/javascript");
		resp.getWriter().print(callback);
		resp.getWriter().println("(");
		resp.getWriter().println("[");
		List<TestData> tds = dao.getTestData(category, testName);
		int len = tds.size();
		int i = 0;
		for (TestData t : tds) {
			resp.getWriter().print("[");
			resp.getWriter().print(t.date - msGmtToEst);
			resp.getWriter().print(",");
			resp.getWriter().print(t.measure);
			resp.getWriter().print("]");
			i++;
			if (len > 1 && i < len) {
				resp.getWriter().print(",");
			}
			resp.getWriter().println();
		}
		LOG.fine("points:" + i + " category:" + category + " testName:"
				+ testName);
		resp.getWriter().println("]);");
	}
}
